﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TA.JSON;
using TA.DotNetUtils;
using System.Collections;

namespace TA.Turbo.Controls
{
	public class ReflectionRepeaterEntries : BaseRepeaterEntries<object>
	{
		#region PUBLIC
		#region INIT
		public ReflectionRepeaterEntries()
		{
		}
		public ReflectionRepeaterEntries(ReflectionRepeaterEntries source)
			: base(source)
		{

		}
		#endregion
		#region EVENTS
		#endregion
		#region PROPS
		#endregion
		#region METHODS
		public override object Clone()
		{
			return new ReflectionRepeaterEntries(this);
		}
		public override object GetValue(int iEntry, string propertyPath)
		{
			return this[iEntry].Eval(propertyPath);
		}
		#endregion
		#endregion
		#region INTERNAL
		#region CONST/STATIC
		#endregion
		#region VARS
		#endregion
		#region PROPS
		#endregion
		#region METHODS
		#region INIT
		#endregion
		#region DATA
		protected override void DoSerializeEntry(JsonWriter jw, object entry)
		{
			this.DoSerializeEntry_Recursive(jw, entry, this.Repeater.Fields);
		}
		private void DoSerializeEntry_Recursive(JsonWriter jw, object entry, ICollection<PropertyPair> fields)
		{
			jw.StartObject();

			foreach (PropertyPair pp in fields)
			{
				object v;
				if (!pp.TryResolve(entry, out v))
				{
					v = entry.Eval(pp.ObjectProperty);
				}

				IEnumerable ev = v is string ? null : v as IEnumerable;

				jw.PropertyName(pp.JSONProperty);

				if (ev == null)
				{
					if (pp.Children.Count == 0 || v == null)
					{
						jw.Value(v);
					}
					else
					{
						this.DoSerializeEntry_Recursive(jw, v, pp.Children);
					}
				}
				else
				{
					jw.StartArray();
					if (pp.Children.Count == 0)
					{
						foreach (object c in ev)
						{
							jw.Value(c);
						}
					}
					else
					{
						foreach (object c in ev)
						{
							this.DoSerializeEntry_Recursive(jw, c, pp.Children);
						}
					}
					jw.EndArray();
				}
			}

			jw.EndObject();
		}
		protected override void DoDeserializeEntry(IJsonReader jr, object entry)
		{
			this.DoDeserializeEntry_Recursive(jr, entry, this.Repeater.Fields);
		}
		private void DoDeserializeEntry_Recursive(IJsonReader jr, object entry, ICollection<PropertyPair> fields)
		{
			jr.Read(JsonToken.StartObject);

			while (jr.TokenType != JsonToken.EndObject)
			{
				string propShortName = (string)jr.Value;
				jr.Read(JsonToken.PropertyName);

				PropertyPair field = fields.First(pp => string.Equals(pp.JSONProperty, propShortName));
				if (jr.TokenType != JsonToken.StartArray)
				{
					if (field.Children.Count == 0)
					{
						object value = jr.Value;
						entry.Store(field.ObjectProperty, value);
					}
					else
					{
						this.DoDeserializeEntry_Recursive(jr, entry.Eval(field.ObjectProperty), field.Children);
					}
				}
				else
				{
					// it's not really possible to deserialize an array
					throw new TurboJsonException("Unable to deserialize an array in JSON input. A manual deserialized has to be used.");
					//jr.Read();
					//if (field.Children.Count == 0)
					//{
					//  ArrayList list = new ArrayList();
					//  while (jr.TokenType != JsonToken.EndArray)
					//  {
					//    list.Add(jr.Value);
					//    jr.Read();
					//  }

					//}
					//else
					//{
					//}
				}
				jr.Read();
			}

			jr.Read(JsonToken.EndObject);
		}
		#endregion
		#region HANDLERS
		#endregion
		#endregion
		#endregion
	}
}
